<template>
  <div class="knowledge-graph-view">
    <div class="sidebar-controls">
      <div class="sidebar-header">
        <h1 class="sidebar-title">知识图谱</h1>
      </div>
      
      <div class="control-section">
        <div class="section-title">节点类型</div>
        <div class="legend">
          <div 
            v-for="type in nodeTypes" 
            :key="type"
            class="legend-item"
          >
            <div class="color-box" :style="{ backgroundColor: getNodeColor(type) }"></div>
            <span class="type-label">{{ type }}</span>
          </div>
        </div>
        <div class="filter-items">
          <el-checkbox 
            v-model="nodeTypeFilters.all" 
            @change="toggleAllNodeTypes"
            class="filter-all"
          >
            全部节点类型
          </el-checkbox>
          <el-divider />
          <div class="filter-grid">
            <el-checkbox 
              v-for="type in nodeTypes" 
              :key="type"
              v-model="nodeTypeFilters[type]"
              :disabled="nodeTypeFilters.all"
              class="filter-item"
            >
              {{ type }}
            </el-checkbox>
          </div>
        </div>
      </div>

      <div class="control-section">
        <div class="section-title">关系类型</div>
        <div class="legend">
          <div 
            v-for="type in relationTypes" 
            :key="type"
            class="legend-item"
          >
            <div class="color-box" :style="{ backgroundColor: getRelationColor(type) }"></div>
            <span class="type-label">{{ type }}</span>
          </div>
        </div>
        <div class="filter-items">
          <el-checkbox 
            v-model="relationTypeFilters.all" 
            @change="toggleAllRelationTypes"
            class="filter-all"
          >
            全部关系类型
          </el-checkbox>
          <el-divider />
          <div class="filter-grid">
            <el-checkbox 
              v-for="type in relationTypes" 
              :key="type"
              v-model="relationTypeFilters[type]"
              :disabled="relationTypeFilters.all"
              class="filter-item"
            >
              {{ type }}
            </el-checkbox>
          </div>
        </div>
      </div>

      <div class="actions">
        <el-button type="primary" @click="loadGraphData" :loading="loading">
          刷新数据
        </el-button>
        <el-button @click="resetGraph">
          重置视图
        </el-button>
      </div>
    </div>

    <div class="graph-area">
      <div v-if="loading" class="loading-overlay">
        <div class="spinner"></div>
        <div>加载中...</div>
      </div>

      <div v-else-if="error" class="error-container">
        <el-empty 
          description="加载图谱数据失败" 
          :image-size="100"
        >
          <el-button @click="loadGraphData">重试</el-button>
        </el-empty>
      </div>

      <div v-else class="graph-container" ref="graphContainer">
        <div v-if="graphData.nodes.length > 0 && !graphRendered" class="graph-loading">
          <div class="spinner"></div>
          <div>渲染中...</div>
        </div>
      </div>

      <div v-if="selectedNode" class="node-info-panel">
        <div class="node-info-header">
          <h3>节点信息</h3>
          <el-button 
            type="text" 
            @click="closeNodeInfo"
            icon="el-icon-close"
          ></el-button>
        </div>
        <div class="node-info-content">
          <div class="info-item">
            <div class="item-label">ID</div>
            <div class="item-value">{{ selectedNode.id }}</div>
          </div>
          <div class="info-item">
            <div class="item-label">名称</div>
            <div class="item-value">{{ selectedNode.name || selectedNode.id }}</div>
          </div>
          <div class="info-item">
            <div class="item-label">类型</div>
            <div class="item-value">
              <el-tag 
                :type="getNodeTypeColor(selectedNode.type)" 
                size="small"
              >
                {{ selectedNode.type }}
              </el-tag>
            </div>
          </div>
          <div 
            v-for="(value, key) in selectedNodeProperties" 
            :key="key"
            class="info-item"
          >
            <div class="item-label">{{ key }}</div>
            <div class="item-value">{{ value }}</div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, reactive, onMounted, computed, onBeforeUnmount, nextTick, watch } from 'vue'
import { ElMessage } from 'element-plus'
import axios from 'axios'
import * as d3 from 'd3'
import { 
  Refresh as ElIconRefresh,
  RefreshRight as ElIconRefreshRight,
  Search as ElIconSearch,
  Close as ElIconClose 
} from '@element-plus/icons-vue'

// 状态定义
const loading = ref(false)
const error = ref(null)
const graphData = ref({ nodes: [], links: [] })
const graphContainer = ref(null)
const simulation = ref(null)
const selectedNode = ref(null)
const searchQuery = ref('')
const confidenceThreshold = ref(0.3)
const selectedEndpoint = ref('test-graph')
const graphRendered = ref(false)
const nodeLimit = ref(150)

// 节点类型过滤器
const nodeTypeFilters = ref({ all: true })

// 关系类型过滤器
const relationTypeFilters = ref({ all: true })

// D3相关变量
let svg = null
let g = null
let zoom = null
let width = 0
let height = 0

// 可用图谱类型
const graphEndpoints = [
  { value: 'graph', label: '标准图谱' },
  { value: 'entity-graph', label: '实体关系图谱' },
  { value: 'test-graph', label: '测试图谱' }
]

// 计算所有可用的节点类型
const nodeTypes = computed(() => {
  const types = new Set()
  graphData.value.nodes.forEach(node => {
    if (node.type) {
      types.add(node.type)
    }
  })
  return Array.from(types)
})

// 计算所有可用的关系类型
const relationTypes = computed(() => {
  const types = new Set()
  graphData.value.links.forEach(link => {
    if (link.type) {
      types.add(link.type)
    }
    // 添加对original_relation的支持
    if (link.original_relation) {
      types.add(link.original_relation)
    }
  })
  return Array.from(types)
})

// 计算节点颜色
const nodeColors = {
  'Malware': '#F56C6C',
  'Vulnerability': '#E6A23C',
  'Tool': '#67C23A',
  'Organization': '#409EFF',
  'Person': '#9C27B0',
  'System': '#2196F3',
  'URL': '#FF9800',
  'File': '#607D8B',
  'Entity': '#4CAF50',  // 绿色，对应图片中的绿色节点
  // 保留原有类型映射
  'Ip': '#F56C6C',
  'Domain': '#E6A23C',
  'Url': '#E6A23C',
  'Email': '#67C23A',
  'Cve': '#F56C6C',
  'Threat_actor': '#F44336', // 红色，对应图片中的红色节点
  'Hash': '#909399',
  'Context': '#409EFF',
  // 新增类型映射，更接近图片中的颜色
  'Location': '#3F51B5',  // 靛蓝色
  'Concept': '#9C27B0',   // 紫色
  'Event': '#E91E63',     // 粉色
  'Activity': '#00BCD4',  // 青色
  '人物': '#9C27B0',       // 紫色，对应图片中的紫色节点
  '事件': '#E91E63',       // 粉色，对应图片中的事件节点
  'Unknown': '#9E9E9E'    // 灰色
}

const getNodeColor = (type) => {
  return nodeColors[type] || '#909399'
}

const getNodeTypeColor = (type) => {
  const colorMap = {
    'Malware': 'danger',
    'Vulnerability': 'warning',
    'Tool': 'success',
    'Organization': 'primary',
    'Person': 'info',
    'System': 'primary',
    'URL': 'warning',
    'File': 'info',
    'Entity': 'info',
    // 保留原有类型映射
    'Ip': 'danger',
    'Domain': 'warning',
    'Url': 'warning',
    'Email': 'success',
    'Cve': 'danger',
    'Threat_actor': 'danger',
    'Hash': 'info',
    'Context': 'primary',
    // 新增类型映射
    'Location': 'primary',
    'Concept': 'info',
    'Event': 'danger',
    'Activity': 'success',
    'Unknown': 'info'
  }
  return colorMap[type] || 'info'
}

// 根据过滤条件计算要显示的节点
const filteredNodes = computed(() => {
  let result = [...graphData.value.nodes]
  
  // 按类型筛选
  if (!nodeTypeFilters.value.all) {
    result = result.filter(node => 
      node.type && nodeTypeFilters.value[node.type])
  }
  
  // 按搜索关键词筛选
  if (searchQuery.value.trim()) {
    const query = searchQuery.value.toLowerCase()
    result = result.filter(node => 
      node.name?.toLowerCase().includes(query) || 
      node.id?.toLowerCase().includes(query))
  }
  
  // 按可信度筛选
  result = result.filter(node => 
    !node.hasOwnProperty('trust_score') || 
    node.trust_score >= confidenceThreshold.value)
  
  // 应用节点数量限制
  return result.slice(0, nodeLimit.value)
})

// 根据过滤条件计算要显示的关系
const filteredLinks = computed(() => {
  if (!graphData.value.links.length) return []
  
  // 获取所有可见节点的ID
  const visibleNodeIds = new Set(filteredNodes.value.map(node => node.id))
  
  let result = graphData.value.links.filter(link => {
    // 确保源节点和目标节点都在筛选后的节点集合中
    const sourceId = typeof link.source === 'object' ? link.source.id : link.source
    const targetId = typeof link.target === 'object' ? link.target.id : link.target
    
    if (!visibleNodeIds.has(sourceId) || !visibleNodeIds.has(targetId)) {
      return false
    }
    
    // 按关系类型筛选 - 考虑type和original_relation
    if (!relationTypeFilters.value.all) {
      const linkType = link.type || link.original_relation
      if (!relationTypeFilters.value[linkType]) {
        return false
      }
    }
    
    // 按可信度筛选
    if (link.trust_score !== undefined && link.trust_score < confidenceThreshold.value) {
      return false
    }
    
    return true
  })
  
  console.log(`筛选后的关系: ${result.length}，类型: ${Array.from(new Set(result.map(link => link.type || link.original_relation))).join(', ')}`)
  return result
})

// 计算选中节点的属性（过滤掉type、id等已显示的字段）
const selectedNodeProperties = computed(() => {
  if (!selectedNode.value) return {}
  
  const excludeFields = ['id', 'name', 'type', 'index', 'x', 'y', 'vx', 'vy', 'fx', 'fy']
  const properties = {}
  
  Object.entries(selectedNode.value).forEach(([key, value]) => {
    if (!excludeFields.includes(key) && value !== undefined && value !== null) {
      properties[key] = value
    }
  })
  
  return properties
})

// 切换所有节点类型
const toggleAllNodeTypes = (val) => {
  Object.keys(nodeTypeFilters.value).forEach(key => {
    nodeTypeFilters.value[key] = val
  })
  updateGraphData()
}

// 切换所有关系类型
const toggleAllRelationTypes = (val) => {
  Object.keys(relationTypeFilters.value).forEach(key => {
    relationTypeFilters.value[key] = val
  })
  updateGraphData()
}

// 初始化图谱
const initGraph = () => {
  if (!graphContainer.value) {
    console.error('Graph container element not found')
    return
  }
  
  console.log('Initializing graph, container size:', graphContainer.value.clientWidth, graphContainer.value.clientHeight)
  
  // 清除现有内容
  d3.select(graphContainer.value).selectAll('*').remove()
  
  // 获取容器尺寸
  const container = graphContainer.value
  width = container.clientWidth || 800 // Set default width if clientWidth is 0
  height = container.clientHeight || 600 // Set default height if clientHeight is 0
  
  // Added fix: ensure container has visible dimensions by setting explicit height
  container.style.height = '600px'
  
  console.log('Container dimensions:', width, height)
  
  // 创建SVG和缩放相关元素
  svg = d3.select(container)
    .append('svg')
    .attr('width', width)
    .attr('height', height)
    .attr('viewBox', `0 0 ${width} ${height}`)
    .attr('class', 'graph-svg')
    .style('background-color', '#21252b')  // 设置深色背景，类似图片效果
  
  console.log('SVG element created')
  
  // 定义箭头
  const defs = svg.append('defs')
  
  // 默认箭头定义
  defs.append('marker')
    .attr('id', 'arrowhead-default')
    .attr('viewBox', '-0 -5 10 10')
    .attr('refX', 25)
    .attr('refY', 0)
    .attr('orient', 'auto')
    .attr('markerWidth', 8)
    .attr('markerHeight', 8)
    .attr('xoverflow', 'visible')
    .append('svg:path')
    .attr('d', 'M 0,-5 L 10 ,0 L 0,5')
    .attr('fill', '#999')
    .style('stroke', 'none')
  
  // 创建主容器
  g = svg.append('g')
  
  // 实现缩放功能
  zoom = d3.zoom()
    .scaleExtent([0.1, 10])
    .on('zoom', (event) => {
      g.attr('transform', event.transform)
    })
  
  svg.call(zoom)
  
  // 初始化力导向图布局
  simulation.value = d3.forceSimulation()
    .force('link', d3.forceLink().id(d => d.id).distance(150))  // 增加连接距离
    .force('charge', d3.forceManyBody().strength(-300))  // 增加排斥力
    .force('center', d3.forceCenter(width / 2, height / 2))
    .force('collide', d3.forceCollide().radius(50))  // 增加碰撞半径
    
  // 更新图谱
  updateGraph()
}

// 更新图谱
const updateGraph = () => {
  console.log('Updating graph visualization')
  if (!g || !simulation.value) {
    console.error('Missing graph elements: g or simulation not initialized')
    return
  }
  
  // 应用筛选条件
  const filteredNodeIds = new Set()
  const nodes = filteredNodes.value
  
  // 将通过筛选的节点ID添加到集合中
  nodes.forEach(node => filteredNodeIds.add(node.id))
  
  console.log(`Filtered nodes: ${nodes.length}`)
  
  // 筛选链接
  const links = graphData.value.links.filter(link => {
    // 确保源节点和目标节点都存在
    if (!filteredNodeIds.has(link.source) && typeof link.source === 'string') {
      return false
    }
    if (!filteredNodeIds.has(link.target) && typeof link.target === 'string') {
      return false
    }
    
    // 应用关系类型筛选
    if (!relationTypeFilters.value.all && !relationTypeFilters.value[link.type]) {
      return false
    }
    
    // 应用可信度筛选
    if (link.trust_score !== undefined && link.trust_score < confidenceThreshold.value) {
      return false
    }
    
    return true
  })
  
  console.log(`Filtered links: ${links.length}`)
  
  // 处理链接中的source和target引用
  const processedLinks = links.map(link => {
    const processedLink = {...link}
    
    // 确保source和target是对象引用而不是字符串ID
    if (typeof processedLink.source === 'string') {
      const sourceNode = nodes.find(n => n.id === processedLink.source)
      if (sourceNode) {
        processedLink.source = sourceNode
      }
    }
    
    if (typeof processedLink.target === 'string') {
      const targetNode = nodes.find(n => n.id === processedLink.target)
      if (targetNode) {
        processedLink.target = targetNode
      }
    }
    
    return processedLink
  }).filter(link => 
    typeof link.source !== 'string' && 
    typeof link.target !== 'string'
  )
  
  console.log(`Final processed links: ${processedLinks.length}`)
  
  try {
    // 清除现有元素
    g.selectAll('.link, .node-group').remove()
    console.log('Cleared existing elements')
    
    // 定义不同关系类型的箭头
    const defs = svg.select('defs')
    // 先清除现有箭头定义
    defs.selectAll('marker').remove()
    
    // 为每种关系类型创建箭头
    const uniqueRelationTypes = new Set()
    
    // 从links中提取所有可能的关系类型
    processedLinks.forEach(link => {
      // 如果有type，添加type
      if (link.type) {
        uniqueRelationTypes.add(link.type)
      }
      
      // 如果有original_relation且与type不同，也添加它
      if (link.original_relation && link.original_relation !== link.type) {
        uniqueRelationTypes.add(link.original_relation)
      }
    })
    
    console.log("箭头定义中的关系类型:", Array.from(uniqueRelationTypes))
    
    // 添加默认箭头定义
    defs.append('marker')
      .attr('id', 'arrowhead-default')
      .attr('viewBox', '-0 -5 10 10')
      .attr('refX', 25)
      .attr('refY', 0)
      .attr('orient', 'auto')
      .attr('markerWidth', 8)
      .attr('markerHeight', 8)
      .attr('xoverflow', 'visible')
      .append('svg:path')
      .attr('d', 'M 0,-5 L 10 ,0 L 0,5')
      .attr('fill', '#999')
      .style('stroke', 'none')
    
    // 为每种唯一的关系类型创建箭头标记
    uniqueRelationTypes.forEach(type => {
      if (type !== 'default') {
        const arrowId = `arrowhead-${type}`
        console.log(`创建箭头标记: ${arrowId}, 颜色: ${getRelationColor(type)}`)
        
        defs.append('marker')
          .attr('id', arrowId)
          .attr('viewBox', '-0 -5 10 10')
          .attr('refX', 25)
          .attr('refY', 0)
          .attr('orient', 'auto')
          .attr('markerWidth', 8)
          .attr('markerHeight', 8)
          .attr('xoverflow', 'visible')
          .append('svg:path')
          .attr('d', 'M 0,-5 L 10 ,0 L 0,5')
          .attr('fill', getRelationColor(type))
          .style('stroke', 'none')
      }
    })
    
    // 创建链接
    const link = g.selectAll('.link')
      .data(processedLinks)
      .enter()
      .append('line')
      .attr('class', 'link')
      .attr('stroke', d => {
        // 如果链接有可信度，根据可信度设置颜色
        if (d.trust_score !== undefined) {
          return getTrustScoreColor(d.trust_score)
        } else {
          // 获取关系类型，确保小写版本也能匹配
          const relType = d.type || d.original_relation || 'default'
          return getRelationColor(relType)
        }
      })
      .attr('stroke-width', 1.8)  // 稍微加粗，更接近图片
      .attr('stroke-opacity', 0.8) // 增加透明度
      .attr('marker-end', d => {
        // 确保链接有类型，并且箭头标记存在
        const linkType = d.type || d.original_relation || 'default'
        console.log(`Link from ${d.source.id} to ${d.target.id} with type ${linkType}`)
        return `url(#arrowhead-${linkType})`
      })
    
    // 添加关系标签
    const linkLabels = g.selectAll('.link-label')
      .data(processedLinks)
      .enter()
      .append('text')
      .attr('class', 'link-label')
      .text(d => d.type || d.original_relation || '')
      .attr('font-size', '10px')
      .attr('text-anchor', 'middle')
      .attr('fill', d => {
        // 如果链接有可信度，使用可信度颜色
        if (d.trust_score !== undefined) {
          return getTrustScoreColor(d.trust_score)
        } else {
          // 获取关系类型，确保小写版本也能匹配
          const relType = d.type || d.original_relation || 'default'
          return getRelationColor(relType)
        }
      })
      .attr('font-weight', 'bold') // 加粗文字
      .attr('dy', -5)
      .style('pointer-events', 'none') // 让标签不阻挡鼠标事件
      .style('user-select', 'none')    // 防止文本被选中
      .style('text-shadow', '0 0 3px rgba(0,0,0,0.6)') // 添加文字阴影提高可读性
    
    console.log('Created links')
    
    // 创建节点组 - 替换之前的节点创建代码
    const nodeGroup = g.selectAll('.node-group')
      .data(nodes)
      .enter()
      .append('g')
      .attr('class', 'node-group')
      .call(d3.drag()
        .on('start', dragstarted)
        .on('drag', dragged)
        .on('end', dragended))
      .on('click', (event, d) => {
        event.stopPropagation()
        selectedNode.value = d
      })
      .on('dblclick', (event, d) => {
        // 添加双击功能，用于固定/解除固定节点
        event.stopPropagation()
        if (d.fx !== null && d.fy !== null) {
          // 节点已固定，解除固定
          d.fx = null
          d.fy = null
          // 更新视觉样式 - 恢复原始边框
          d3.select(event.currentTarget).select('circle')
            .transition()
            .duration(300)
            .attr('stroke', '#fff')
            .attr('stroke-width', 1.5)
        } else {
          // 节点未固定，固定在当前位置
          d.fx = d.x
          d.fy = d.y
          // 更新视觉样式 - 添加黄色边框指示固定状态
          d3.select(event.currentTarget).select('circle')
            .transition()
            .duration(300)
            .attr('stroke', '#FFFF00')
            .attr('stroke-width', 2.5)
        }
      });
    
    // 添加节点圆形背景
    nodeGroup.append('circle')
      .attr('class', 'node')
      .attr('r', 20)  // 设置合适的半径
      .attr('fill', d => {
        // 首先检查节点是否有自己的color属性
        if (d.color) {
          return d.color;
        }
        // 如果节点有可信度评分，基于可信度选择颜色
        else if (d.trust_score !== undefined) {
          return getTrustScoreColor(d.trust_score)
        } else {
          return getNodeColor(d.type)
        }
      })
      .attr('stroke', '#fff')
      .attr('stroke-width', 1.5)
      .attr('stroke-opacity', 0.9)
      .on('mouseover', function(event, d) {
        d3.select(this)
          .transition()
          .duration(200)
          .attr('r', 25)  // 悬停时放大
          .attr('stroke-width', 2.5)
      })
      .on('mouseout', function(event, d) {
        // 如果节点不是固定状态，恢复正常样式
        const isFixed = d.fx !== null && d.fy !== null && !d.tempDrag
        d3.select(this)
          .transition()
          .duration(200)
          .attr('r', 20)
          .attr('stroke-width', isFixed ? 2.5 : 1.5)
          .attr('stroke', isFixed ? '#FFFF00' : '#fff')
      });
    
    // 添加节点文字
    nodeGroup.append('text')
      .attr('dy', '.35em')
      .attr('text-anchor', 'middle')
      .attr('fill', 'white')  // 白色文字
      .attr('font-size', '10px')
      .attr('pointer-events', 'none')  // 防止文字拦截鼠标事件
      .text(d => {
        // 文本截断
        const text = d.name || d.id;
        return text.length > 10 ? text.substring(0, 8) + '...' : text;
      });
    
    console.log('Created nodes')
    
    // 更新模拟
    simulation.value
      .nodes(nodes)
      .on('tick', ticked)
    
    simulation.value.force('link').links(processedLinks);
    
    // 增加排斥力，让节点分布更均匀
    simulation.value.force('charge', d3.forceManyBody().strength(-300));
    
    // 增加碰撞检测半径，防止节点重叠
    simulation.value.force('collide', d3.forceCollide().radius(50));
    
    simulation.value.alpha(1).restart();
    
    console.log('Started simulation');
    
    // 添加点击空白区域关闭节点信息的功能
    svg.on('click', () => {
      selectedNode.value = null;
    });
    
    // 自动居中视图
    resetGraph();
    
    // Mark as rendered
    graphRendered.value = true;
  } catch (error) {
    console.error('Error updating graph:', error);
    ElMessage.error('更新图谱时发生错误');
  }
}

// 拖拽开始
function dragstarted(event, d) {
  if (!event.active) simulation.value.alphaTarget(0.3).restart();
  
  // 保存原始位置 - 用于临时拖动
  if (d.fx === null && d.fy === null) {
    d.tempDrag = true; // 标记为临时拖动
  }
  
  d.fx = d.x;
  d.fy = d.y;
  
  // 添加视觉反馈
  d3.select(event.sourceEvent.currentTarget).select('circle')
    .transition()
    .duration(200)
    .attr('stroke', '#FFFF00')
    .attr('stroke-width', 2.5);
}

// 拖拽中
function dragged(event, d) {
  d.fx = event.x;
  d.fy = event.y;
}

// 拖拽结束
function dragended(event, d) {
  if (!event.active) simulation.value.alphaTarget(0);
  
  // 如果是临时拖动（没有通过双击固定），则拖拽结束后释放节点
  if (d.tempDrag) {
    d.fx = null;
    d.fy = null;
    d.tempDrag = false;
    
    // 恢复原始边框样式
    d3.select(event.sourceEvent.currentTarget).select('circle')
      .transition()
      .duration(200)
      .attr('stroke', '#fff')
      .attr('stroke-width', 1.5);
  }
}

// 重置图谱视图
const resetGraph = () => {
  if (!svg || !g) return
  
  svg.transition()
    .duration(750)
    .call(zoom.transform, d3.zoomIdentity
      .translate(width / 2, height / 2)
      .scale(0.8)
      .translate(-width / 2, -height / 2))
}

// 加载图谱数据
const loadGraphData = async () => {
  loading.value = true
  error.value = null
  graphRendered.value = false
  
  try {
    console.log('Loading graph data from endpoint:', selectedEndpoint.value)
    
    // 从后端API获取数据，使用正确的后端URL
    const url = `http://localhost:8000/${selectedEndpoint.value}`
    console.log('Fetching graph data from:', url)
    
    // 获取认证令牌
    const token = localStorage.getItem('token')
    
    // 设置请求头，包含认证信息
    const headers = {}
    if (token) {
      headers['Authorization'] = `Bearer ${token}`
    }
    
    const response = await axios.get(url, { headers })
    
    if (response.data && response.data.nodes && response.data.links) {
      console.log('Raw API response:', response.data)
      
      // 检查API返回的关系类型
      if (response.data.relationship_types) {
        console.log('API返回的关系类型:', response.data.relationship_types)
      } else {
        // 分析链接中的关系类型
        const linkTypes = new Set()
        response.data.links.forEach(link => {
          if (link.type) linkTypes.add(`type: ${link.type}`)
          if (link.original_relation) linkTypes.add(`original_relation: ${link.original_relation}`)
        })
        console.log('从链接中提取的关系类型:', Array.from(linkTypes))
      }
      
      // 处理从API接收到的数据
      graphData.value = {
        nodes: response.data.nodes.map(node => ({
          ...node,
          // 确保节点有id和type属性
          id: node.id || `node-${Math.random().toString(36).substring(2, 9)}`,
          type: node.type || 'Unknown',
          name: node.name || node.label || node.id
        })),
        links: response.data.links.map(link => ({
          ...link,
          // 确保链接有source、target和type属性
          id: link.id || `link-${Math.random().toString(36).substring(2, 9)}`,
          source: link.source,
          target: link.target,
          // 优先使用链接的type属性，如果没有则使用original_relation，最后默认为"关联"
          type: link.type || link.original_relation || '关联'
        }))
      }
      
      // 添加日志，输出所有节点类型和可能的关系类型
      const nodeTypes = new Set(graphData.value.nodes.map(node => node.type))
      console.log('节点类型:', Array.from(nodeTypes))
      
      const relationTypesFromLinks = new Set()
      graphData.value.links.forEach(link => {
        if (link.type) relationTypesFromLinks.add(link.type)
        if (link.original_relation) relationTypesFromLinks.add(link.original_relation)
      })
      console.log('链接中的关系类型:', Array.from(relationTypesFromLinks))
      
      console.log(`Loaded ${graphData.value.nodes.length} nodes and ${graphData.value.links.length} links`)
      
      // 初始化过滤器
      initFilters()
      
      // 创建图谱
      nextTick(() => {
        initGraph()
        forceRenderGraph()
      })
    } else {
      throw new Error('Invalid data format received from API')
    }
  } catch (err) {
    console.error('Error loading graph data:', err)
    error.value = err.message || '加载数据失败'
  } finally {
    loading.value = false
  }
}

// 替换fetchGraphData函数，使用loadGraphData
const fetchGraphData = loadGraphData

// 导出图谱数据
const exportGraphData = () => {
  const data = JSON.stringify({
    nodes: filteredNodes.value,
    links: filteredLinks.value
  }, null, 2)
  
  const blob = new Blob([data], { type: 'application/json' })
  const url = URL.createObjectURL(blob)
  
  const a = document.createElement('a')
  a.href = url
  a.download = `knowledge-graph-${new Date().toISOString().slice(0, 10)}.json`
  document.body.appendChild(a)
  a.click()
  document.body.removeChild(a)
  URL.revokeObjectURL(url)
}

// 初始化过滤器
const initFilters = () => {
  // 节点类型过滤器
  nodeTypes.value.forEach(type => {
    if (nodeTypeFilters.value[type] === undefined) {
      nodeTypeFilters.value[type] = true
    }
  })
  
  // 关系类型过滤器
  console.log("初始化关系类型过滤器，开始")
  
  // 获取所有可能的关系类型，包括original_relation
  const allRelationTypes = new Set()
  
  // 记录initFilters时的关系类型状态
  console.log("初始化过滤器时的relationTypes:", relationTypes.value)
  
  // 直接从链接中提取关系类型，不依赖计算属性
  graphData.value.links.forEach(link => {
    if (link.type) {
      allRelationTypes.add(link.type)
      console.log(`添加关系类型(type): ${link.type}`)
    }
    if (link.original_relation) {
      allRelationTypes.add(link.original_relation)
      console.log(`添加关系类型(original_relation): ${link.original_relation}`)
    }
  })
  
  // 将所有关系类型添加到过滤器中
  Array.from(allRelationTypes).forEach(type => {
    if (relationTypeFilters.value[type] === undefined) {
      console.log(`将关系类型添加到过滤器: ${type}`)
      relationTypeFilters.value[type] = true
    }
  })
  
  // 确保所有关系类型都被添加到控制台
  console.log("过滤器初始化后的所有关系类型:", Object.keys(relationTypeFilters.value))
}

// 处理搜索
const handleSearch = () => {
  updateGraphData()
}

// 关闭节点信息面板
const closeNodeInfo = () => {
  selectedNode.value = null
}

// 组件挂载时初始化图谱
onMounted(() => {
  loadGraphData()
  
  // Add resize observer to handle container size changes
  const resizeObserver = new ResizeObserver(() => {
    console.log('Container resized, reinitializing graph')
    if (graphContainer.value && graphData.value.nodes.length > 0) {
      nextTick(() => {
        initGraph()
        updateGraph()
      })
    }
  })
  
  if (graphContainer.value) {
    resizeObserver.observe(graphContainer.value)
  }
  
  // Set a timeout to reinitialize the graph after 1 second
  // This helps in cases where the container is not properly sized initially
  setTimeout(() => {
    if (graphContainer.value && graphData.value.nodes.length > 0) {
      console.log('Forcing graph reinitialization after timeout')
      initGraph()
      updateGraph()
    }
  }, 1000)
  
  // 组件销毁前清理
  onBeforeUnmount(() => {
    if (simulation.value) {
      simulation.value.stop()
    }
    
    resizeObserver.disconnect()
  })
})

// 添加关系颜色
const relationColors = {
  'ATTRIBUTEDTO': '#FF9800',
  'TARGETS': '#2196F3',
  'USES': '#4CAF50',
  'CONTAINS': '#9C27B0',
  'COMMUNICATESWITH': '#E91E63',
  'LOCATED': '#3F51B5',
  'MITIGATES': '#8BC34A',
  'EXPLOITS': '#F44336',
  // 添加Neo4j中常见的关系类型（都转为小写以便匹配）
  'discoveredin': '#FFC107',
  'exploits': '#F44336',
  'has': '#4CAF50',
  'hasalias': '#9C27B0',
  'hasauthor': '#3F51B5',
  'indicates': '#E91E63',
  'isa': '#00BCD4',
  'targets': '#2196F3',
  'uses': '#8BC34A',
  'variantof': '#FF5722',
  // 添加特定应用的小写关系类型
  'discovered_in': '#FFC107',
  'has_alias': '#9C27B0',
  'has_author': '#3F51B5',
  'is_a': '#00BCD4',
  'variant_of': '#FF5722',
  // 添加中文关系类型
  '关联': '#999999',
  '属于': '#2196F3',
  '包含': '#9C27B0',
  '作用于': '#4CAF50',
  '起源于': '#FF5722',
  '引起': '#F44336',
  '导致': '#E91E63',
  '监测': '#3F51B5',
  '预防': '#4CAF50',
  '提供': '#8BC34A',
  '研发': '#00BCD4',
  '控制': '#673AB7',
  '产生': '#FFC107',
  '确定': '#607D8B',
  '协调': '#009688',
  '指导': '#03A9F4',
  '需要': '#FF9800'
}

const getRelationColor = (type) => {
  if (!type) return '#999999'
  
  // 转为小写以进行不区分大小写的查找
  const lowerType = type.toLowerCase()
  
  // 检查小写键是否存在
  if (relationColors[lowerType]) {
    return relationColors[lowerType]
  }
  
  // 尝试原始键
  return relationColors[type] || '#999999'
}

// 监听筛选变化，重新渲染图谱
watch([filteredNodes, filteredLinks], () => {
  updateGraph()
})

// 更新图谱数据
const updateGraphData = () => {
  // 根据筛选器更新图谱数据
  console.log('Updating graph data with filters', { 
    selectedTypes: Object.keys(nodeTypeFilters.value).filter(key => nodeTypeFilters.value[key] && key !== 'all')
  })
  
  // 根据节点类型筛选节点
  filteredNodes.value = graphData.value.nodes
    .filter(node => {
      // 检查节点类型筛选
      if (!nodeTypeFilters.value.all) {
        // 如果"全部"未选中，则检查具体类型
        if (!nodeTypeFilters.value[node.type]) {
          return false
        }
      }
      
      return true
    })
  
  // 获取筛选后节点的ID列表
  const nodeIds = new Set(filteredNodes.value.map(node => node.id))
  
  // 筛选连接，只保留筛选后节点间的连接
  filteredLinks.value = graphData.value.links
    .filter(link => {
      const sourceId = typeof link.source === 'object' ? link.source.id : link.source
      const targetId = typeof link.target === 'object' ? link.target.id : link.target
      
      // 确保源节点和目标节点都在筛选后的节点集合中
      if (!nodeIds.has(sourceId) || !nodeIds.has(targetId)) {
        return false
      }
      
      return true
    })
  
  console.log(`After filtering: ${filteredNodes.value.length} nodes, ${filteredLinks.value.length} links`)
  
  // 更新图谱
  forceRenderGraph()
}

// 强制重新渲染图谱
const forceRenderGraph = () => {
  console.log('Force rendering graph')
  if (!graphContainer.value || !filteredNodes.value.length) return
  
  // 确保容器有合适的尺寸
  const container = graphContainer.value
  if (!container.clientWidth || !container.clientHeight) {
    console.log('Container has no dimensions, setting default size')
    container.style.width = '100%'
    container.style.height = '600px'
  }
  
  // 延迟短暂时间重新渲染，确保DOM已更新
  setTimeout(() => {
    if (svg && g) {
      console.log('Re-rendering existing graph')
      updateGraph()
      
      // 标记为已渲染
      graphRendered.value = true
    } else {
      console.log('Creating new graph')
      initGraph()
      updateGraph()
      
      // 标记为已渲染
      graphRendered.value = true
    }
  }, 300)
}

// 监听筛选器变更
watch([nodeTypeFilters], () => {
  if (graphData.value.nodes.length) {
    updateGraphData()
  }
}, { deep: true })

// 在ticked函数内更新链接和标签位置
function ticked() {
  // 更新链接位置
  g.selectAll('.link')
    .attr('x1', d => d.source.x)
    .attr('y1', d => d.source.y)
    .attr('x2', d => d.target.x)
    .attr('y2', d => d.target.y);
  
  // 更新链接标签位置
  g.selectAll('.link-label')
    .attr('x', d => (d.source.x + d.target.x) / 2)
    .attr('y', d => (d.source.y + d.target.y) / 2);
  
  // 更新节点组位置
  g.selectAll('.node-group')
    .attr('transform', d => `translate(${d.x}, ${d.y})`);
}

// 获取可信度颜色 - 根据图片中的颜色梯度
const getTrustScoreColor = (score) => {
  const scorePercent = Math.floor(score * 100)
  
  if (scorePercent < 10) return '#FF0000'       // 红色 0-9
  if (scorePercent < 20) return '#FF3300'       // 红橙色 10-19
  if (scorePercent < 30) return '#FF6600'       // 橙红色 20-29
  if (scorePercent < 40) return '#FF9900'       // 橙色 30-39
  if (scorePercent < 50) return '#FFCC00'       // 橙黄色 40-49
  if (scorePercent < 60) return '#FFFF00'       // 黄色 50-59
  if (scorePercent < 65) return '#CCFF00'       // 黄绿色 60-64
  if (scorePercent < 70) return '#99FF00'       // 黄绿色 65-69
  if (scorePercent < 75) return '#66FF00'       // 黄绿色 70-74
  if (scorePercent < 80) return '#33FF00'       // 浅绿色 75-79
  if (scorePercent < 85) return '#00FF00'       // 绿色 80-84
  if (scorePercent < 90) return '#00CC00'       // 深绿色 85-89
  if (scorePercent < 95) return '#009900'       // 更深绿色 90-94
  return '#006600'                              // 最深绿色 95-100
}
</script>

<style scoped>
.knowledge-graph-view {
  display: flex;
  width: 100%;
  height: calc(100vh - 120px);
  overflow: hidden;
}

.sidebar-controls {
  width: 320px;
  background-color: #1e2124;
  color: #eee;
  padding: 20px;
  overflow-y: auto;
  flex-shrink: 0;
  box-shadow: 2px 0 10px rgba(0, 0, 0, 0.3);
  display: flex;
  flex-direction: column;
}

.sidebar-header {
  margin-bottom: 25px;
  text-align: center;
  padding-bottom: 20px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
  position: relative;
}

.sidebar-header::after {
  content: "";
  position: absolute;
  bottom: -1px;
  left: 50%;
  transform: translateX(-50%);
  width: 60px;
  height: 3px;
  background-color: #3498db;
  border-radius: 3px;
}

.sidebar-title {
  font-size: 22px;
  font-weight: bold;
  color: #fff;
  margin: 0;
  letter-spacing: 1px;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
}

.section-title {
  font-size: 16px;
  font-weight: bold;
  margin-bottom: 15px;
  color: #fff;
  position: relative;
  padding-bottom: 8px;
}

.section-title::after {
  content: "";
  position: absolute;
  bottom: 0;
  left: 0;
  width: 40px;
  height: 2px;
  background-color: #3498db;
}

.control-section {
  margin-bottom: 25px;
  padding-bottom: 20px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}

.filter-items {
  max-height: 300px;
  overflow-y: auto;
  padding: 8px;
  background-color: rgba(0, 0, 0, 0.2);
  border-radius: 8px;
  margin-top: 10px;
}

.filter-grid {
  display: grid;
  grid-template-columns: repeat(1, 1fr);
  gap: 10px;
  padding: 5px;
}

.actions {
  display: flex;
  gap: 12px;
  justify-content: center;
  margin-top: auto;
  padding-top: 20px;
}

.actions .el-button {
  padding: 10px 20px;
  font-weight: 600;
}

/* 图例样式 */
.legend {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-bottom: 15px;
  background-color: rgba(0, 0, 0, 0.2);
  border-radius: 8px;
  padding: 12px;
  max-height: 250px;
  overflow-y: auto;
  scrollbar-width: thin;
}

.legend::-webkit-scrollbar,
.filter-items::-webkit-scrollbar {
  width: 6px;
}

.legend::-webkit-scrollbar-thumb,
.filter-items::-webkit-scrollbar-thumb {
  background-color: rgba(255, 255, 255, 0.2);
  border-radius: 3px;
}

.legend::-webkit-scrollbar-track,
.filter-items::-webkit-scrollbar-track {
  background-color: rgba(0, 0, 0, 0.1);
  border-radius: 3px;
}

.legend-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 5px;
  transition: background-color 0.2s;
  border-radius: 4px;
}

.legend-item:hover {
  background-color: rgba(255, 255, 255, 0.1);
}

.color-box {
  width: 18px;
  height: 18px;
  border-radius: 4px;
  border: 1px solid rgba(255, 255, 255, 0.3);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
}

/* 修改Element Plus组件样式 */
:deep(.el-checkbox) {
  margin-right: 0;
  margin-bottom: 2px;
  color: #ddd;
}

:deep(.el-checkbox__label) {
  color: #ddd;
}

:deep(.el-checkbox__input.is-checked + .el-checkbox__label) {
  color: #fff;
}

:deep(.el-divider) {
  background-color: rgba(255, 255, 255, 0.1);
  margin: 15px 0;
}

:deep(.el-checkbox__input.is-checked .el-checkbox__inner) {
  background-color: #3498db;
  border-color: #3498db;
}

:deep(.el-checkbox__inner:hover) {
  border-color: #3498db;
}

.graph-area {
  flex-grow: 1;
  position: relative;
  background: #21252b;
  overflow: hidden;
}

.graph-container {
  width: 100%;
  height: 100%;
  background-color: #21252b;
}

.loading-overlay, .error-container, .graph-loading {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  background-color: rgba(0, 0, 0, 0.5);
  color: white;
  z-index: 10;
}

.spinner {
  width: 50px;
  height: 50px;
  border: 5px solid rgba(255, 255, 255, 0.2);
  border-top-color: #3498db;
  border-radius: 50%;
  animation: spin 1s linear infinite;
  margin-bottom: 15px;
}

@keyframes spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}

.node-info-panel {
  position: absolute;
  bottom: 20px;
  right: 20px;
  width: 300px;
  background-color: rgba(34, 38, 46, 0.9);
  border-radius: 8px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.3);
  z-index: 100;
  color: #eee;
}

.node-info-header {
  padding: 10px 15px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  border-bottom: 1px solid #383c40;
}

.node-info-header h3 {
  margin: 0;
  font-size: 16px;
}

.node-info-content {
  padding: 15px;
  max-height: 300px;
  overflow-y: auto;
}

.info-item {
  margin-bottom: 8px;
  display: flex;
  align-items: flex-start;
}

.item-label {
  width: 80px;
  font-weight: bold;
  color: #bbb;
  font-size: 12px;
}

.item-value {
  flex: 1;
  word-break: break-all;
  font-size: 12px;
}

/* D3样式 */
:deep(.graph-svg) {
  width: 100%;
  height: 100%;
  cursor: move;
  background-color: #21252b;
}

:deep(.node) {
  cursor: pointer;
  stroke: #fff;
  stroke-width: 1.5px;
}

:deep(.link) {
  stroke-opacity: 0.6;
  stroke-width: 1.5px;
}

:deep(.node-label) {
  fill: #fff;
  pointer-events: none;
  font-size: 12px;
  font-weight: bold;
}

/* 节点类型样式 */
:deep(.node-type-Entity) {
  fill: #4CAF50;
}

:deep(.node-type-Threat_actor) {
  fill: #F44336;
}

.type-label {
  font-size: 14px;
  font-weight: 500;
  white-space: normal;
  word-break: break-word;
  line-height: 1.3;
  flex: 1;
}

.filter-all {
  margin-left: 8px;
  font-weight: 600;
}

.filter-item {
  padding: 5px 0;
}
</style> 